#ifndef __MY_DATA__
#define __MY_DATA__
/*
    数据管理模块：
    1.数据管理类的实现
*/
#include <ctime>
#include <unordered_map>
#include <pthread.h>
#include "util.hpp"
#include "config.hpp"
namespace cloud
{

    //备份信息结构体
    typedef struct BackupInfo
    {
        int pack_flag; // 是否压缩的标志
        time_t mtime;
        time_t atime;
        size_t fsize;
        std::string real_path;   //文件真实存储的路径
        std::string pack_path;   //文件的压缩路径
        std::string url;    //统一资源定位符

        void NewBackupInfo(const std::string &realpath)
        {
            Config *config = Config::GetInstance();
            std::string packdir = config->GetPackDir();
            std::string packsuffix = config->GetPackFileSuffix();
            std::string download_prefix = config->GetDownloadPrefix();

            FileUtil fu(realpath);
            this->pack_flag = false;
            this->fsize = fu.FileSize();
            this->mtime = fu.LastMTime();
            this->atime = fu.LastAtime();
            this->real_path = realpath;     //文件的真实路径，打开文件路径

            // ./backdir/a.txt   ->  ./packdir/a.txt.lz
            this->pack_path = packdir + fu.FileName() + packsuffix;

            //./backdir/a.txt    ->  /download/a.txt
            this->url = download_prefix + fu.FileName();
        }
    } BackupInfo;


    //数据管理模块
    class DataManager
    {
    private:
        std::string _backup_file;
        pthread_rwlock_t _rwlock;
        std::unordered_map<std::string, BackupInfo> _table;

    public:
        DataManager()
        {
            _backup_file = Config::GetInstance()->GetBackupFile();
            
            pthread_rwlock_init(&_rwlock, nullptr); // 初始化读写锁
            
            InitLoad();
        }
        bool Insert(const BackupInfo &info) // 插入，是修改
        {
            pthread_rwlock_wrlock(&_rwlock); // 申请写锁
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock); // 释放锁
            Storage();    //及时存储
            return true;
        }
        bool Update(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock); // 申请写锁
            _table[info.url] = info;
            pthread_rwlock_unlock(&_rwlock); // 释放锁
            Storage();    //及时存储
            return true;
        }
        bool GetOneByUrl(const std::string &url, BackupInfo *info)
        {
            pthread_rwlock_wrlock(&_rwlock); // 因为要查找表，是操作table，也得需要加锁
            auto it = _table.find(url);
            if (it == _table.end()) // 没找到
            {
                pthread_rwlock_unlock(&_rwlock);
                return false;
            }
            // 找到了
            *info = it->second;
            pthread_rwlock_unlock(&_rwlock);
            return true;
        }
        bool GetOneByRealpath(const std::string &path, BackupInfo *info)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for (; it != _table.end(); it++)
            {
                if(it->second.real_path == path)
                {
                    *info = it->second;
                    pthread_rwlock_unlock(&_rwlock);
                    return true;
                }
            }
            //没找到
            pthread_rwlock_unlock(&_rwlock);
            return false;
        }
        bool GetAll(std::vector<BackupInfo> *arry)
        {
            pthread_rwlock_wrlock(&_rwlock);
            auto it = _table.begin();
            for(;it!=_table.end();it++)
            {
                arry->push_back(it->second);
            }
            pthread_rwlock_unlock(&_rwlock);
            return true;

            pthread_rwlock_unlock(&_rwlock);

            return true;
        }

        bool Storage()
        {
            //1.获取所有数据
            std::vector<BackupInfo> arry;
            GetAll(&arry);
            //2.添加到Json::Value
            Json::Value root;
            for(int i = 0;i<arry.size();i++)
            {
                Json::Value item;
                item["pack_flag"] = arry[i].pack_flag;
                item["mtime"] = arry[i].mtime;
                item["atime"] = arry[i].atime;
                item["fsize"] = arry[i].fsize;
                item["real_path"] = arry[i].real_path;
                item["url"] = arry[i].url;
                item["pack_path"] = arry[i].pack_path;
                root.append(item);
            }
            //3.对Json::Value序列化
            std::string body;
            JsonUtil::Serialize(root, &body);
            //4.写文件
            FileUtil fu(_backup_file);
            fu.SetContent(&body);

            return true;
        }
        bool InitLoad()
        {
            //1.将数据文件中的数据读取出来
            FileUtil fu(_backup_file);
            std::cout<<_backup_file<<std::endl;

            if(fu.Exists() == false)   //没有文件，不用加载
            {
                return true;
            }
                

            std::string body;
            fu.GetContent(&body);
            //2.反序列化
            Json::Value root;
            JsonUtil::UnSerialize(body, &root);
            //3.将反序列化得到的json::value中的数据添加到table中
            for(int i = 0;i<root.size();i++)
            {
                BackupInfo info;
                info.pack_flag = root[i]["pack_flag"].asBool();
                info.fsize = root[i]["fsize"].asInt64();
                info.atime = root[i]["atime"].asInt64();
                info.mtime = root[i]["mtime"].asInt64();
                info.pack_path = root[i]["pack_path"].asString();
                info.real_path = root[i]["real_path"].asString();
                info.url = root[i]["url"].asString();
                Insert(info);
            }

            return true;
        }

        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock); // 销毁读写锁
        }
    };

}

#endif